package com.koron.device.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.koron.device.bean.Equipment;
import com.koron.device.mapper.EquipmentMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
public class DeviceUtils {

    /**
     * 设备信息修正
     * 修改字段如下
     * level 1 由parent_id 与 id的关系确定
     * level_code 1 等于sort，有先前的sort确定，sort需要重排
     * level_path 1 由parent_id 与 id的关系确定
     * full_path_code 1 由parent_id 与 id的关系确定
     * full_path_name 1 由parent_id 与 id的关系确定
     * sort 1 sort顺序不变，但sort需要重排
     */
    @TaskAnnotation("deviceRectify")
    public Boolean deviceRectify(SessionFactory factory) {
        EquipmentMapper mapper = factory.getMapper(EquipmentMapper.class);
        // 扁平的list（children为空）
        List<Equipment> equipments = mapper.getChildrenById(null, null, 1);
        JSONArray tree = listToTree(JSON.parseArray(JSON.toJSONString(equipments)), "id", "parentId", "children");
        // 树状的list（children有值）
        List<Equipment> treeVos = JSONArray.parseArray(JSONArray.toJSONString(tree), Equipment.class);
        // key:id  value:equipment(children不为空)
        Map<String, Equipment> idMap = equipments.stream().collect(Collectors.toMap(Equipment::getId, item -> item));
        configDeviceLevel(treeVos, idMap);
        // 将树状转成扁平的list
        List<Equipment> vos = new ArrayList<>();
        treeDeviceToList(treeVos, vos);
        ForkJoinTask deviceRectify = new ForkJoinTask(0, vos.size(), vos, mapper, "deviceRectify");
        int row = deviceRectify.compute();
        log.info("设备level、level_code、level_path、full_path_code、full_path_name修正完成， size = {}", vos.size());
        equipments.clear();
        tree.clear();
        treeVos.clear();
        idMap.clear();
        vos.clear();
        return true;
    }

    /**
     * @param vos 树状的list
     * @param idMap id和设备的映射
     */
    private void configDeviceLevel(List<Equipment> vos, Map<String, Equipment> idMap) {
        Iterator<Equipment> iterator = vos.iterator();
        while (iterator.hasNext()) {
            Equipment vo = iterator.next();
            if(!StringUtils.equals(vo.getParentId(), "0")) {
                if(!idMap.containsKey(vo.getParentId())) {
                    continue;
                }
                // 如果有父节点，则在上一次递归时，已经设置了正确的sort
                Equipment parent = idMap.get(vo.getParentId());
                // 1、level
                vo.setLevel(parent.getLevel() + 1);
                // 3、level_path
                vo.setLevelPath(parent.getLevelPath() + "/" + vo.getSort());
                // 4、full_path_name
                vo.setFullPathName(parent.getFullPathName() + "/" + vo.getName());
                // 5、full_path_code
                vo.setFullPathCode(parent.getFullPathCode() + "/" + vo.getId());
            } else {
                // 如果是根节点
                vo.setLevel(1);
                vo.setSort(1);
                vo.setLevelPath("1");
                vo.setFullPathName(vo.getName());
                vo.setFullPathCode(vo.getId());
            }
            // 2、level_code
            vo.setLevelCode(vo.getSort());
            idMap.put(vo.getId(), vo);
            if(!CollectionUtils.isEmpty(vo.getChildren())) {
                List<Equipment> children = vo.getChildren();
                Collections.sort(children, Comparator.comparingInt(Equipment::getSort));
                Stream.iterate(0, i -> i + 1).limit(children.size()).forEach(i -> children.get(i).setSort((i + 1)));
                vo.setChildren(children);
                configDeviceLevel(vo.getChildren(), idMap);
            }
        }
    }

    /**
     * 按照字段id, parentId, children，将list转成tree
     * @param arr
     * @param id
     * @param pid
     * @param child
     * @return
     */
    public JSONArray listToTree(JSONArray arr,String id,String pid,String child){
        JSONArray r = new JSONArray();
        JSONObject hash = new JSONObject(new LinkedHashMap());
        for(int i=0;i<arr.size();i++){
            JSONObject json = (JSONObject) arr.get(i);
            hash.put(json.getString(id), json);
        }
        for(int j=0;j<arr.size();j++){
            JSONObject aVal = (JSONObject) arr.get(j);
            JSONObject hashVP = (JSONObject) hash.get(aVal.get(pid).toString());
            if(hashVP!=null){
                if(hashVP.get(child)!=null){
                    JSONArray ch = (JSONArray) hashVP.get(child);
                    ch.add(aVal);
                    hashVP.put(child, ch);
                }else{
                    JSONArray ch = new JSONArray();
                    ch.add(aVal);
                    hashVP.put(child, ch);
                }
            }else{
                r.add(aVal);
            }
        }
        return r;
    }

    private void treeDeviceToList(List<Equipment> treeVos, List<Equipment> vos) {
        for (int i = 0; i < treeVos.size(); i++) {
            vos.add(treeVos.get(i));
            if(!CollectionUtils.isEmpty(treeVos.get(i).getChildren())) {
                treeDeviceToList(treeVos.get(i).getChildren(), vos);
            }
        }
    }

}
